package net.lzzy.practices.aspects;

import net.lzzy.practices.entities.User;
import net.lzzy.practices.service.UserService;
import net.lzzy.practices.utils.AspectUtil;
import net.lzzy.practices.utils.JwtUtil;
import net.lzzy.practices.web.models.ApiResult;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.UUID;

/**
 * @author AndyStern
 */
@Aspect
@Component
public class CourseAspect {
    private final UserService service;

    @Autowired
    public CourseAspect(UserService service) {
        this.service = service;
    }

    @Pointcut("execution(* net.lzzy.practices.web.courses.CourseApiController.getCourses(..)) || " +
            "execution(* net.lzzy.practices.web.courses.CourseApiController.getOpenCourses(..)) ||" +
            "execution(* net.lzzy.practices.web.courses.CourseApiController.getPagedCourses(..)) || " +
            "execution(* net.lzzy.practices.web.courses.CourseApiController.getPagedOpenCourses(..))")
    private void coursePoint(){

    }

    @Pointcut("execution(* net.lzzy.practices.web.courses.CourseApiController.getTeacherCourses(..)) || " +
            "execution(* net.lzzy.practices.web.courses.CourseApiController.add(..)) || " +
            "execution(* net.lzzy.practices.web.courses.CourseApiController.update(..)) ||" +
            "execution(* net.lzzy.practices.web.courses.CourseApiController.openClose(..)) ||" +
            "execution(* net.lzzy.practices.web.courses.CourseApiController.delete(..))")
    private void teacherPoint(){}

    @Pointcut("execution(* net.lzzy.practices.web.courses.CourseApiController.getStudentCourses(..))")
    private void studentPoint(){

    }

    @Around("coursePoint()")
    public ApiResult aroundCourseMethods(ProceedingJoinPoint point) throws Throwable {
        int[] allowRoles = new int[]{User.TYPE_STUDENT, User.TYPE_TEACHER};
        return checkAndProceed(point, allowRoles);
    }

    private ApiResult checkAndProceed(ProceedingJoinPoint point, int[] allowRoles) throws Throwable {
        String token = AspectUtil.getToken(point);
        String uid = JwtUtil.verifyToken(token);
        if (uid == null) {
            return new ApiResult(false, "认证信息已失效，请重新登录！", null);
        }
        User user = service.getById(UUID.fromString(uid));
        if (user == null) {
            return new ApiResult(false, "认证信息无效，请登录！", null);
        }
        if (Arrays.stream(allowRoles).noneMatch(role -> role == user.getType())) {
            return new ApiResult(false, "没有权限", null);
        }
        return (ApiResult) point.proceed();
    }

    @Around("teacherPoint()")
    public ApiResult aroundTeacherMethods(ProceedingJoinPoint point) throws Throwable {
        int[] allowRoles = new int[]{ User.TYPE_TEACHER};
        return checkAndProceed(point,allowRoles);
    }

    @Around("studentPoint()")
    public ApiResult aroundStudentMethods(ProceedingJoinPoint point) throws Throwable {
        int[] allowRoles = new int[]{User.TYPE_STUDENT};
        return checkAndProceed(point,allowRoles);
    }
}
